﻿using System;
using System.ComponentModel.DataAnnotations;
using System.Reactive.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.Windows;
using System.Windows.Controls;
using GalaSoft.MvvmLight.Messaging;
using ManagerClient.AuthentificationService;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Unity;

namespace ManagerClient.Authentification.Logic
{
    public class LoginWindowViewModel : ViewModelBase
    {
        private const string PROTOCOL_NAME = "net.tcp://";
        private const string port = "8997";
        private readonly IUnityContainer container;
        private AuthentificationServiceClient client;
        private string hostAddress;
        private bool isBusy;
        private string login;

        public LoginWindowViewModel(IUnityContainer container)
        {
            OkCommand = new DelegateCommand<object>(Authenicate, CanExecOk);

            this.container = container;
            try
            {
//TODO:remove!!!
            }
            catch (Exception e)
            {
            }
        }

        public DelegateCommand<object> OkCommand { get; private set; }

        [Required(ErrorMessage = @"Поле ""Логин"" необходимо заполнить")]
        public string Login
        {
            get { return login; }
            set
            {
                if (login != value)
                {
                    login = value;
                    OkCommand.CanExecute(true);
                    RaisePropertyChanged(() => Login);
                }
            }
        }

        public string HostAddress
        {
            get { return hostAddress; }
            set
            {
                hostAddress = value;
                RaisePropertyChanged(() => HostAddress);
            }
        }


        public bool IsBusy
        {
            get { return isBusy; }
            set
            {
                isBusy = value;
                RaisePropertyChanged(() => IsBusy);
            }
        }

        public bool IsAuthentificated { get; set; }

        public void NotifyWindowToClose()
        {
            Messenger.Default.Send(
                new NotificationMessage(this, "CloseWindowsBoundToMe"));
        }

        private bool CanExecOk(object arg)
        {
            if (!string.IsNullOrWhiteSpace(Login))
            {
                return true;
            }
            return false;
        }


        private void Authenicate(object password)
        {
            //TODO: implement correct call
            IsBusy = true;
            string pass = ((PasswordBox) password).Password;

            Authentificate(pass);
        }

        private void ShowMainWindow()
        {
            var m = new MainWindow();
            m.DataContext = container.Resolve<MainViewModel>();
            m.Show();
        }

        private void Authentificate(String password)
        {
            try
            {
                var myEndpointAddress = new EndpointAddress(
                    new Uri(
                        String.Format(
                            PROTOCOL_NAME +
                            "{0}:{1}/Logon",
                            HostAddress, port)));

                client = new AuthentificationServiceClient("NetTcpBinding_IAuthentificationService");

                //передача данных о пользователе
                var clientCredentials = new ClientCredentials();
                clientCredentials.UserName.UserName = Login;
                clientCredentials.UserName.Password = password;
                //пересоздаем прокси
                client.ChannelFactory.Endpoint.Behaviors.Remove(typeof (ClientCredentials));
                client.ChannelFactory.Endpoint.Behaviors.Add(clientCredentials);
                client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode =
                    X509CertificateValidationMode.None;
                client.ClientCredentials.ServiceCertificate.Authentication.CustomCertificateValidator =
                    new MyX509CertificateValidator("offDinner");
                container.RegisterInstance(client, new ContainerControlledLifetimeManager());

                IObservable<bool> func = Observable.FromAsyncPattern<string, string, bool>(
                    client.BeginValidateUser, client.EndValidateUser)(Login, password);
                func.ObserveOnDispatcher().
                     Finally(() => { IsBusy = false; }
                    )
                    .
                     Subscribe(x =>
                         {
                             if (x)
                             {
                                 IsAuthentificated = true;
                                 ShowMainWindow();
                                 NotifyWindowToClose();
                             }
                         }
                               ,
                               e =>
                                   {
                                       IsAuthentificated = false;
                                       MessageBox.Show("Login or password is invalid",
                                                       "Authentification error: " + e.StackTrace);
                                   });
            }
            catch (Exception e)
            {
                MessageBox.Show("Адрес хоста указан некорректно");
            }
        }
    }
}